package toolx

import (
	"errors"
	"reflect"
	"strings"
)

func StructToMapByTag(tag string, v interface{}) (map[string]interface{}, error) {
	if tag == "" {
		tag = "excel"
	}
	rv := reflect.ValueOf(v)
	if !rv.IsValid() || rv.Kind() != reflect.Ptr || rv.IsNil() {
		return nil, errors.New("unsuport type")
	}
	rv = reflect.Indirect(rv)
	rt := reflect.TypeOf(v)
	rte := rt.Elem()
	switch rte.Kind() {
	case reflect.Struct:
		return rvToMap(rv, tag), nil
	default:
		return nil, errors.New("only support struct")
	}
}

func StructListToMapByTag(tag string, v []interface{}) ([]map[string]interface{}, error) {
	if tag == "" {
		tag = "excel"
	}
	rv := reflect.ValueOf(v)
	if !rv.IsValid() || rv.Kind() != reflect.Ptr || rv.IsNil() {
		return nil, errors.New("unsuport type")
	}

	var m []map[string]interface{}
	for _, item := range v {
		m = append(m, rvToMap(reflect.ValueOf(item), tag))
	}
	return m, nil
}

func rvToMap(rv reflect.Value, tag string) map[string]interface{} {
	rt := rv.Type()
	var m map[string]interface{}
	for i := 0; i < rt.NumField(); i++ {
		fld := rt.Field(i)
		key := fld.Tag.Get(tag)
		options := strings.Split(key, ",")
		key = options[0]
		// if t == "" || t == "-" {
		// 	return nil, fmt.Errorf("invalid tag;field: %v", fld.Name)
		// }
		if key != "" && key == "-" {
			if fld.IsExported() {
				m[key] = rv.Field(i).Interface()
			}
		}
	}

	return m
}
